/*******************************************************************************
 * Copyleft (c) 2021 Kcode
 *
 * @file    disp_manager.c
 * @brief   显示设备管理者文件
 * @author  K
 * @version 0.0.1
 * @date    2021-07-02
 * @license MulanPSL-1.0
 *
 * 文件修改历史：
 * <时间>       | <版本>    | <作者>  | <描述>
 * 2021-07-02   | v0.0.1    | Kcode   | 显示设备管理者文件
 * -----------------------------------------------------------------------------
 ******************************************************************************/

#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H

#include "pic_operation.h"
#include "video_recv_manager.h"

/*!
 * 图标布局信息 
 */
typedef struct Layout {
	char *strIconName;			/**< 图标的名字 */  
	int TopLeftX;				/**< 图标左上角x坐标 */
	int TopLeftY;				/**< 图标左上角y坐标 */
	int BotRightX;				/**< 图标右下角x坐标 */
	int BotRightY;				/**< 图标右下角x坐标 */
}T_Layout, *PT_Layout;

/*!
 * 内存页面数据是否被使用 
 */
typedef enum {
	VMS_FREE = 0,			/**< 空闲 */
	VMS_USED_FOR_PREPARE,	/**< 子线程占用 */
	VMS_USED_FOR_CURMAIN,	/**< 当前主线程占用 */
}E_VideoMemState;

/*!
 * 内存页面数据是否已准备好 
 */
typedef enum {
	PS_BLANK = 0,			/**< 数据空白 */
	PS_GENERATING,			/**< 数据生成中 */
	PS_GENERATED,			/**< 数据完毕 */
}E_PicState;

/*!
 * 描述页面内存块 
 */
typedef struct VideoMem {
	int id;                             /**< 页面的id */
	int isDevFB;    /**< 1: 这个VideoMem是显示设备的显存; 0: 只是一个普通缓存 */
	E_VideoMemState eVideoMemState;     /**< 这个VideoMem的状态 */
	E_PicState ePicState;               /**< VideoMem中内存里图片的状态 */
	T_PIXELDATAS tPixelDatas;           /**< 内存: 用来存储图像 */
	struct VideoMem *ptNext;            /**< 链表结点 */
}T_VideoMem, *PT_VideoMem;

/*!
 * 显示模块结构体
 */
typedef struct DispOpr {
	char *name;     /**< 显示模块的名字 */
	unsigned char *pDispMem;    /**< 显存地址 */
	int Xres;       /**< X分辨率 */
	int Yres;       /**< Y分辨率 */
	int Bpp;        /**< 一个像素用多少位来表示 */
	int LineWidth;  /**< 一行数据占据多少字节 */

    /* 设备初始化函数 */
	int (*DeviceInit)(void); 

    /* 设备退出函数 */
    int (*DeviceExit)(void);

    /* 清屏为某颜色 */
	int (*CleanScreen)(unsigned int BackColor);

    /* 把指定座标的象素设为某颜色 */
	int (*ShowPixel)(int PenX, int PenY, unsigned int Color);  

    /* 显示一页,数据源自ptVideoMem */
	int (*ShowPage)(PT_PIXELDATAS ptVideoMem);
	struct DispOpr *ptNext; /**< 链表结点 */
}T_DispOpr, *PT_DispOpr;

/*!
 * @brief  根据名字取出指定的"显示模块"
 * @param  pName[in] 名字
 * @return NULL：失败,没有指定的模块, 非NULL：显示模块的PT_DispOpr结构体指针
 */
PT_DispOpr GetDispOpr(char *pName);

/*!
 * @brief  注册"显示模块", 把所能支持的显示设备的操作函数放入链表
 * @param  ptDispOpr[in]  一个结构体,内含显示设备的操作函数
 * @return 0：注册成功，其他值：失败
 */
int RegisterDispOpr(PT_DispOpr ptDispOpr);

/*!
 * @brief  显示本程序能支持的"显示模块"
 * @param  [in] 无 [out]无
 * @return 无
 */
void ShowDispOpr(void);

/*!
 * @brief  注册显示设备
 * @param  [in] 无
 * @return 0：成功，其他值：失败
 */
int DisplayInit(void);

/*!
 * @brief  注册"framebuffer显示设备"
 * @param  [in] 无
 * @return 0：成功，其他值：失败
 */
int FBInit(void);

/*!
 * @brief  获得所使用的显示设备的分辨率和BPP
 * @param  pXres[out] 存X分辨率
 * @param  pYres[out] 存Y分辨率
 * @param  pbpp[out]  存bpp
 * @return 0：成功，-1：失败(未使用SelectAndInitDefaultDispDev来选择显示模块)
 */
int GetDispResolution(int *pXres, int *pYres, int *pBpp);

/*!
 * @brief  根据名字取出指定的"显示模块", 调用它的初始化函数, 并且清屏
 * @param  name[in] 名字
 * @return 无
 */
void SelectAndInitDefaultDispDev(char *name);

/*!
 * @brief  显示模块清理工作
 * @param  [in] 无
 * @return 无
 */
void ExitDispDev(void);

/*!
 * @brief  VideoMem: 为加快显示速度,我们事先在缓存中构造好显示的页面的数据,
 *         (这个缓存称为VideoMem)显示时再把VideoMem中的数据复制到设备的显存上
 * @param  num[in] 所要分配的内存数量
 * @return 0：成功，-1：失败(未使用SelectAndInitDefaultDispDev来选择显示模块)
 */
int AllocVideoMem(int num);

/*!
 * @brief  获得一块可操作的VideoMem(它用于存储要显示的数据), 用完后用PutVideoMem来释放
 * @param  id[in] ID值,先尝试在众多VideoMem中找到ID值相同的
 * @param  isCurMain[in] 1表示当前程序马上要使用VideoMem,无法如何都要返回一个VideoMem
 *                       0表示这是为了改进性能而提前取得VideoMem,不是必需的
 * @return NULL：失败，没有可用的VideoMem，非NULL：成功,返回PT_VideoMem结构体
 */
PT_VideoMem GetVideoMem(int id, int isCurMain);

/*!
 * @brief  使用GetVideoMem获得的VideoMem, 用完时用PutVideoMem释放掉
 * @param  ptVideoMem[in] 使用完毕的VideoMem
 * @return 无
 */
void PutVideoMem(PT_VideoMem ptVideoMem);

/*!
 * @brief  程序事先用SelectAndInitDefaultDispDev选择了显示模块,本函数返回该显示模块
 * @return 显示模块的PT_DispOpr结构体指针
 */
PT_DispOpr GetDefaultDispDev(void);

/*!
 * @brief  把VideoMem中内存全部清为某种颜色
 * @param  ptVideoMem[in] VideoMem结构体指针, 内含要操作的内存
 * @param  dwColor[in]    设置为该颜色
 * @return 无
 */
void ClearVideoMem(PT_VideoMem ptVideoMem, unsigned int color);

/*!
 * @brief  获得显示设备的显存, 在该显存上操作就可以直接在LCD上显示出来
 * @param  [in] 无
 * @return 无
 */
PT_VideoMem GetDevVideoMem(void);
void SetFontSize(unsigned int FontSize);
/*!
 * @brief  把VideoMem中内存的指定区域全部清为某种颜色
 * @param  ptVideoMem[in] VideoMem结构体指针, 内含要操作的内存
 * @param  ptLayout[in]   矩形区域, 指定了左上角,右在角的坐标
 * @param  dwColor[in]    设置为该颜色
 * @return 无
 */
void ClearVideoMemRegion(PT_VideoMem ptVideoMem, 
                        PT_Layout ptLayout, unsigned int dwColor);

/*!
 * @brief  获得显示设备的显存, 在该显存上操作就可以直接在LCD上显示出来
 * @param  [in] 无
 * @return 无
 */
int GetVideoBufForDisplay(PT_VIDEOBUF framebuf);

/*!
 * @brief  刷新像素数据到设备职工
 * @param  pixel_data[in] 像素数据
 * @return 无
 */
void FlushPixelDatasToDev(PT_PIXELDATAS pixel_data);

int CRTInit(void);

#endif /* _DISP_MANAGER_H */

